# encoding:utf8

import os
import sys
import copy
import json
import shutil
import logging
from mgamedev.py_lib.dhttp import DHTTPUtil
from xlchk import chk_call

from mgamedev.py_lib.luabase import LuabaseTool as Luabase
import git
from git import Repo

GIT_MUST_GITREPO = dict(
    HALL="HALL",
    SHOP="SHOP",
    MODULES="MODULES"
)

LUAV_KEY_STRING = dict(
    CFGMODULES="ENUM_MODULESTYPE",
    PROJ="PROJ"
)

VER_TAG = '''
__VER_{repo}__ = "{ver}"
'''


def add_path_prefix(path_str):
    if sys.platform != "win32":
        return path_str

    if path_str.startswith("\\\\?\\"):
        return path_str

    ret = "\\\\?\\" + os.path.abspath(path_str)
    ret = ret.replace("/", "\\")
    return ret


def copy_dirfiles_to(fromdir, todir):
    if not os.path.isdir(todir):
        os.makedirs(todir)
    for item in os.listdir(fromdir):
        path = os.path.join(fromdir, item)
        if os.path.isfile(path):
            path = add_path_prefix(path)
            copy_dst = add_path_prefix(todir)
            shutil.copy(path, copy_dst)
        if os.path.isdir(path):
            new_dst = os.path.join(todir, item)
            if not os.path.isdir(new_dst):
                os.makedirs(add_path_prefix(new_dst))
            copy_dirfiles_to(path, new_dst)


class _XLMake(Luabase):

    _githall = None
    _gitshop = None
    _gitmodules = None

    _musthandle_mods = {}
    _verrecord = {}  # record the git vers

    def __init__(self, luaf):
        Luabase.__init__(self)
        self.lua_dofile(luaf)

    def __init_gitrepo(self, gitname):
        luav_proj = self.lua_val(LUAV_KEY_STRING["PROJ"])
        gitrepo = self.__chk_gitbranch(gitname, luav_proj[gitname].path)
        if gitrepo:
            gittag = luav_proj[gitname].gittag if luav_proj[gitname].gittag != None else self.lua_val(
                "%s_NEWEST_TAG" % gitname)
            print(gittag,  "--->>>>gittag")
            setattr(self, "_git" + gitname.lower(), gitrepo)
            self.__async_repo(gitrepo, gittag)
            self._verrecord[gitname] = gittag
        else:
            self.raise_err("Init git-repo faild!<%s>" % gitname)

    def __chk_gitbranch(self, gitkey, gitpath):
        try:
            gitrepo = Repo(gitpath)
        except git.exc.NoSuchPathError as nperr:
            self.raise_err("Chk [%s=%s] path exist? \n", gitkey, nperr)
        except git.exc.InvalidGitRepositoryError as giterr:
            self.raise_err(
                "Chk [%s=%s] is a git-base path? \n", gitkey, giterr)
        logging.info("GIT-%s path path is ->>%s", gitkey, gitpath)
        gitrepo.git.fetch(all=True)
        return gitrepo

    def __async_repo(self, gitrepo, gittag):
        gitref = None
        bname = ""
        for refres in gitrepo.references:
            if refres.name == gittag.encode("utf8"):
                gitref = refres
                bname = refres.name
                if (isinstance(refres, git.refs.head.Head)):
                    refres.checkout()
                elif (isinstance(refres, git.refs.tag.TagReference)):
                    if bname in gitrepo.branches:
                        gitrepo.branches[bname].checkout()
                    else:
                        gitrepo.git.checkout(bname, b=bname)
                else:
                    self.raise_err("Unknow error!")

        if not gitref:
            self.raise_err("Not find the tag<%s> in repo |%s|" %
                           (gittag, gitrepo.common_dir))

    def __chkout_gitrepo(self):
        logging.info("Chk the git-proj path...")
        for _, gitkey in self._musthandle_mods.items():
            self.__init_gitrepo(gitkey)
        logging.info("Done!\n")

    def execute(self):
        logging.info("************************")
        # create temporary-dir
        path_temp = self.lua_val("path_temporary")
        dir_temp = self.crt_tempdir(path_temp)
        # chk mod to handle
        must_handlemod = copy.copy(GIT_MUST_GITREPO)
        if (self.lua_val("is_halldev")):
            must_handlemod.pop("HALL")
        self._musthandle_mods = must_handlemod
        # chkout git-repo
        self.__chkout_gitrepo()
        # handle_path
        func_ = ""
        for _, gitkey in self._musthandle_mods.items():
            func_ = "handle_" + gitkey.lower()
            try:
                funcexe_ = self.__getattribute__(func_)
            except:
                pass
            if hasattr(funcexe_, "__call__"):
                funcexe_(dir_temp)
        # chk copy2work dir
        path_workdir = self.lua_val("path_workproj")
        if path_workdir:
            copy_dirfiles_to(path_temp, path_workdir)
            with open(os.path.join(path_workdir, "xl_ver.json"), "w+") as fp:
                fp.write(json.dumps(self._verrecord))
        logging.info("**********DONE!***********")


class XLMake(_XLMake):

    def __init__(self, *args, **kwads):
        _XLMake.__init__(self, *args, **kwads)

    def handle_hall(self, tarpath):
        logging.info("Handle <HALL> ing...")
        luav_hall = self.lua_val("PROJ").HALL
        path_proj = os.path.dirname(self._githall.common_dir)
        path_src = path_proj + "/trunk/src/xlhall"
        path_res = path_proj + "/trunk/res/res_xlhall"

        path_tarsrc = tarpath + \
            ("/src" if not luav_hall.srct_path else "/" + luav_hall.srct_path)
        path_tarres = tarpath + \
            ("/res" if not luav_hall.rest_path else "/" + luav_hall.rest_path)

        lualist = luav_hall.ignore_file
        ignore_list = []
        for _, luav in lualist.items():
            ignore_list.append(luav)
        ignore_filter = shutil.ignore_patterns(*ignore_list)

        shutil.copytree(path_src, path_tarsrc)
        shutil.copytree(path_res, path_tarres, ignore=ignore_filter)

    def handle_shop(self, tarpath):
        logging.info("Handle <SHOP> ing...")
        luav_shop = self.lua_val("PROJ").SHOP
        path_proj = os.path.dirname(self._gitshop.common_dir)

        path_src = path_proj + "/src/app/amodule"
        path_res = path_proj + "/res/amodule"

        path_tarsrc = tarpath + "/src/app/amodule"
        path_tarres = tarpath + "/res/amodule"

        shutil.copytree(path_src, path_tarsrc)
        shutil.copytree(path_res, path_tarres)

    def handle_modules(self, tarpath):
        logging.info("Handle <MODULES> ing...")
        path_proj = os.path.dirname(self._gitmodules.common_dir)

        path_src = path_proj + "/src/app/amodule"
        path_res = path_proj + "/res/amodule"

        path_tarsrc = tarpath + "/src/app/amodule"
        path_tarres = tarpath + "/res/amodule"

        # MUST
        MODULE_MUST_COPY = self.lua_val("MODULE_MUST_COPY")
        MODULE_SRC_COPY = self.lua_val("MODULE_SRC_COPY")
        MODULE_RES_COPY = self.lua_val("MODULE_RES_COPY")
        for _, mpath in MODULE_MUST_COPY.items():
            modpath = path_tarsrc + mpath
            shutil.copytree(path_src + mpath, modpath)

        # ALL MODULE
        luav_modules = self.lua_val("PROJ").MODULES
        list_modules = luav_modules.modules
        is_opa = False
        is_sys = False

        for _, mod in list_modules.items():
            mod = mod.encode("utf8")
            if mod in MODULE_SRC_COPY["SPECIAL"]:
                shutil.copytree(path_src + MODULE_SRC_COPY["SPECIAL"][mod],
                                path_tarsrc + MODULE_SRC_COPY["SPECIAL"][mod])

                shutil.copytree(path_res + MODULE_RES_COPY["SPECIAL"][mod],
                                path_tarres + MODULE_RES_COPY["SPECIAL"][mod])
            elif mod in MODULE_SRC_COPY["SYS"]:
                is_sys = True
                shutil.copytree(path_src + MODULE_SRC_COPY["SYS"][mod],
                                path_tarsrc + MODULE_SRC_COPY["SYS"][mod])

                shutil.copytree(path_res + MODULE_RES_COPY["SYS"][mod],
                                path_tarres + MODULE_RES_COPY["SYS"][mod])
            elif mod in MODULE_SRC_COPY["ACTIVITY"]:
                is_opa = True
                shutil.copytree(path_src + MODULE_SRC_COPY["ACTIVITY"][mod],
                                path_tarsrc + MODULE_SRC_COPY["ACTIVITY"][mod])
                shutil.copytree(path_res + MODULE_RES_COPY["ACTIVITY"][mod],
                                path_tarres + MODULE_RES_COPY["ACTIVITY"][mod])

        def copy_sepfile(path_, tpath_):
            for filename in os.listdir(path_):
                fileobj = os.path.join(path_, filename)
                if os.path.isfile(fileobj):
                    shutil.copyfile(fileobj, os.path.join(tpath_, filename))

        # SEP FILES
        path_sep = ""
        if is_sys:
            path_sep = self.lua_val("MODULE_RELAY")["sys"]
            copy_sepfile(path_src + path_sep, path_tarsrc + path_sep)
        if is_opa:
            path_sep = self.lua_val("MODULE_RELAY")["opa"]
            copy_sepfile(path_src + path_sep, path_tarsrc + path_sep)
            path_reslay = self.lua_val("MODULE_RES_RELAY")["opa"]
            shutil.copytree(path_res + path_reslay,
                            path_tarres + path_reslay)  # res 下的common也得拷贝


__all__ = [
    "XLMake"
]

if __name__ == "__main__":
    print("======================================")
    print("============XLMakev0.9.3=============")
    print("======================================")

    def bin_call():
        mk = XLMake("makecfg")
        ret = DHTTPUtil.download_file("/conf/cfgxlmake.lua")
        mk.lua_dostring(ret)
        mk.execute()

    chk_call(bin_call)
